#ifndef PREF_MENU_H_
#define PREF_MENU_H_

#include "../widgets.h"
#include "p_icon.h"

namespace gpyp {
namespace pref {

class Menu : public Gtk::VBox {
private:
  class Selector : public SelectorComboBox<ConfMenu::RefMenu> {
  public:
    Selector(Application &app);
  };

  class Editor;
  class Manager : boost::noncopyable {
    friend class Editor;
  private:
    Editor               &editor_;
    Manager              *parent_;
    ConfMenu::RefMenu     menu_;
    Gtk::TreeNodeChildren children_;

    autoconn              conn_item_added_;
    autoconn              conn_item_removed_;
    autoconn              conn_item_reordered_;
    autoconn              conn_cleared_;

  protected:
    Gtk::TreeIter get_iter(ConfMenu::RefMenu item);
    ConfMenu::RefMenu get_item(const Gtk::TreeIter &iter);

    void on_item_added(ConfMenu::RefMenu item);
    void on_item_removed(ConfMenu::RefMenu item);
    void on_item_reordered(ConfMenu::RefMenu item,
                           ConfMenu::RefMenu prev,
                           ConfMenu::RefMenu next);
    void on_cleared();

  public:
    void up(ConfMenu::RefMenu item);
    void down(ConfMenu::RefMenu item);

    Manager *get_parent();
    ConfMenu::RefMenu get_menu();

    Manager(Editor &editor, Manager *parent,
            ConfMenu::RefMenu menu, Gtk::TreeNodeChildren children);
  };
  typedef boost::shared_ptr<Manager> RefManager;
  class Editor : public TreeView {
    friend class Manager;
  private:
    Gtk::TreeModelColumn<ConfMenu::RefMenu> column_item_;
    Gtk::TreeModelColumn<RefManager>        column_manager_;
    Gtk::TreeModelColumnRecord              columns_;
    Glib::RefPtr<Gtk::TreeStore>            treestore_;

    CellRendererIcon                        renderer_icon_;
    Gtk::CellRendererText                   renderer_label_;
    Gtk::CellRendererText                   renderer_command_;
    Gtk::TreeViewColumn                     column_icon_;
    Gtk::TreeViewColumn                     column_label_;
    Gtk::TreeViewColumn                     column_command_;

    ConfMenu::RefMenu                       menu_;
    RefManager                              manager_;

  protected:
    ConfMenu::RefMenu get_item(const Gtk::TreeIter &iter);
    ConfMenu::RefMenu get_item(const Gtk::TreePath &path);
    ConfMenu::RefMenu get_item(const Glib::ustring &path);

    void icon_on_cell_data(Gtk::CellRenderer *cell, const Gtk::TreeIter &iter);
    void label_on_cell_data(Gtk::CellRenderer *cell, const Gtk::TreeIter &iter);
    void command_on_cell_data(Gtk::CellRenderer *cell, const Gtk::TreeIter &iter);

    void icon_on_edited(const Glib::ustring &path, const Glib::ustring &new_icon_name);
    void label_on_edited(const Glib::ustring &path, const Glib::ustring &new_text);
    void command_on_edited(const Glib::ustring &path, const Glib::ustring &new_text);

  private:
    void add_item(sigc::slot<ConfMenu::RefMenu, Manager &> func);

    inline ConfMenu::RefMenu add_item_cb(Manager &parent, ConfMenu::RefMenu (ConfMenu::Menu::*func)()) {
      return (parent.get_menu().get()->*func)();
    }
    inline void add_item(ConfMenu::RefMenu (ConfMenu::Menu::*func)()) {
      add_item(sigc::bind(sigc::mem_fun(*this, &Editor::add_item_cb), func));
    }
    inline ConfMenu::RefMenu add_sp_cb(Manager              &parent,
                                       const Glib::ustring  &label,
                                       ConfMenu::SpecialType sptype) {
      return parent.get_menu().get()->add_special(label, sptype);
    }

  public:
    void up();
    void down();
    void add();
    void add_separator();
    void add_special(const Glib::ustring  &label,
                     ConfMenu::SpecialType sptype);
    void add_child();
    void remove();

    void set(ConfMenu::RefMenu menu);

    Editor(Application &app, Gtk::Window &parent);
  };

private:
  Selector selector_;
  Editor   editor_;

  Gtk::Menu     menu_sp_;
  Gtk::MenuItem mi_sp_playwith_;

private:
  void sp_playwith_on_activate();
  void add_special_on_clicked();

public:
  Menu(Application &app, Gtk::Window &parent);
};

}/*pref*/
}/*gpyp*/

#endif/*PREF_MENU_H_*/
